﻿// ....................................................................................................................
//	Author: Copyright (C) 2012 Ing. Marek Hubal
//	Email: hubal@acasoftware.org
// ....................................................................................................................

using System;

namespace core
{
    /// <summary>Trieda INodeList</summary>
    public class INodeList_SMB_SHARES : INodeList
    {
        protected string FExpandPath; // Cesta na expandovanie
        protected int FExpand_Level;
        protected int FExpand_EntriesRead;
        protected IntPtr FExpand_Buffer;
        protected int FExpand_Result;
        protected IntPtr FExpand_ResumeHandle;
        protected int FExpand_CurrentIndex;

        public bool ExpandMode_AddAdminShare; // Priznak zaradenie admin zdielani do expandovania

        /// <summary>Otvorenie cache pre zapis</summary>
        /// <param name="pCacheID">ID cache</param>
        /// <returns>true / false</returns>
        protected override bool BeginWriteCache(string pCacheID)
        {
            return false;
        }

        /// <summary>Konstruktor</summary>
        public INodeList_SMB_SHARES(string pExpandPath = "")
        {
            // Inicializacia
            ID = NODE_LIST_ID_SMB_SHARES;
            FColsCount = 4;
            FEnableVisibilityMask = 0xe; FDefVisibilityMask = 0xf;
            FExpandPath = pExpandPath;
            ExpandMode_AddAdminShare = IApp.Settings.FileExplorer_ShowAdminShares;
        }

        /// <summary>Ziskanie nazvu stlpca</summary>
        /// <param name="pIndex">pozicia</param>
        /// <returns>nazov alebo prazdny retazec</returns>
        public override string GetColumnName(int pIndex)
        {
            switch (pIndex)
            {
                case 0: return lang.NODE_LIST_SMB_SHARES_TEXT_1;
                case 1: return lang.NODE_LIST_SMB_SHARES_TEXT_2;
                case 2: return lang.NODE_LIST_SMB_SHARES_TEXT_3;
                case 3: return lang.NODE_LIST_SMB_SHARES_TEXT_4;
                default: return "";
            }
        }
        /// <summary>Property: CurrentPath</summary>
        public override string CurrentPath
        {
            get
            {
                return FExpandPath;
            }
        }
        /// <summary>Property: KeyValue</summary>
        public override string KeyValue
        {
            get
            {
                return IFileSystem.ExtractName(CurrentPath).ToLower();
            }
        }
        /// <summary>Property: DeviceRootPath</summary>
        public override string DeviceRootPath
        {
            get
            {
                return "\\\\";
            }
        }
        /// <summary>Property: IsSlowDevice</summary>
        public override bool IsSlowDevice
        {
            get
            {
                return true;
            }
        }
        /// <summary>Test ci sa node moze expandovat</summary>
        /// <param name="pIndex">pozicia</param>
        /// <returns>true / false</returns>
        public override bool CanNodeExpand(int pIndex)
        {
            INode N = this[pIndex];
            if (N == null) return false; // Ziskam platny node

            switch (N.ID)
            {
                case INode.NODE_ID_SMB_SHARE:
                    return true;
                default: return false;
            }
        }
        /// <summary>Ziskanie expandovacej cesty node</summary>
        /// <param name="pIndex">pozicia</param>
        /// <returns>cesta</returns>
        public override string GetNodeExpandPath(int pIndex)
        {
            INode N = this[pIndex];
            if (N == null) return ""; // Ziskam platny node

            switch (N.ID)
            {
                case INode.NODE_ID_SMB_SHARE: return IFileSystem.AppendToPath(CurrentPath, ((INodeData_SMB_SHARE)N.NodeData).ShareNetName);
                default: return "";
            }
        }

        /// <summary>Zaciatok expandovania obsahu</summary>
        /// <param name="pFilter">objekt filtra</param>
        /// <returns>0 alebo kod chyby</returns>
        public override int BeginExpand(INodeFilters pFilter = null)
        {
            FExpand_Level = 2; FExpand_Buffer = IntPtr.Zero;
            FState = 1; // Nastavim mode expand
            return 0;
        }
        /// <summary>Uzatvorenie aktualneho expandu</summary>
        public override void CloseExpand()
        {
            if (FExpand_Buffer != IntPtr.Zero) IWin32.Netapi32.NetApiBufferFree(FExpand_Buffer);
            FExpand_Buffer = IntPtr.Zero;
            FState = 0; // Nastavim normalny mod
        }
        /// <summary>Expandovanie dalsieho zaznamu</summary>
        /// <param name="Result">ulozeny obsah najdeneho zaznamu alebo null ak sa ma zaznam pripojit do zoznamu</param>
        /// <returns>0 - ziaden dalsi zaznam, 1 - najdeny zaznam alebo kod chyby</returns>
        public override int ExpandNext(INodeFilters pFilter = null, INode Result = null)
        {
            try
            {
                int totalEntries;
                if (FExpand_Buffer == IntPtr.Zero)
                {
                    if (Result == null) { INode N1 = new INode(); N1.ID = INode.NODE_ID_BACK_ITEM; AddNode(N1); } // Vytvorim prvy back item node

                    // Prvy expand
                    FExpand_Result = IWin32.Netapi32.NetShareEnum(IFileSystem.ExtractName(FExpandPath), FExpand_Level, out FExpand_Buffer, 200, out FExpand_EntriesRead, out totalEntries, ref FExpand_ResumeHandle);
                    if (FExpand_Result == IWin32.ERROR_ACCESS_DENIED)
                    {
                        FExpand_Level = 1; // Znizim level
                        FExpand_Result = IWin32.Netapi32.NetShareEnum(IFileSystem.ExtractName(FExpandPath), FExpand_Level, out FExpand_Buffer, 200, out FExpand_EntriesRead, out totalEntries, ref FExpand_ResumeHandle);
                    }

                    if ((FExpand_Result != IWin32.ERROR_SUCCESS) && (FExpand_Result != IWin32.ERROR_MORE_DATA))
                    {
                        switch (FExpand_Result)
                        {
                            case 5: LastError = lang.NODE_LIST_SMB_SHARES_TEXT_7; break;
                            case 53: LastError = lang.NODE_LIST_SMB_SHARES_TEXT_7_1; break;
                            default: LastError = ""; break;
                        }
                        return -1;
                    }
                    FExpand_CurrentIndex = 0;
                }

                while (true)
                {
                    if (FExpand_CurrentIndex >= FExpand_EntriesRead)
                    {
                        if (FExpand_Result == IWin32.ERROR_SUCCESS) return 0; // Nie su dalsie data?

                        if (FExpand_Buffer != IntPtr.Zero) IWin32.Netapi32.NetApiBufferFree(FExpand_Buffer); // Uvolnim buffer
                        FExpand_Buffer = IntPtr.Zero;

                        FExpand_Result = IWin32.Netapi32.NetShareEnum(IFileSystem.ExtractName(FExpandPath), FExpand_Level, out FExpand_Buffer, 200, out FExpand_EntriesRead, out totalEntries, ref FExpand_ResumeHandle);
                        if ((FExpand_Result != IWin32.ERROR_SUCCESS) && (FExpand_Result != IWin32.ERROR_MORE_DATA)) return 0; // Ziadne dalsie nebudu?
                        FExpand_CurrentIndex = 0;
                    }

                    Type t = (FExpand_Level == 2) ? typeof(IWin32.SHARE_INFO_2) : typeof(IWin32.SHARE_INFO_1);
                    int offset = System.Runtime.InteropServices.Marshal.SizeOf(t);

                    int lpItem = FExpand_Buffer.ToInt32() + offset * FExpand_CurrentIndex;

                    INode N = Result == null ? new INode() : Result;
                    N.ID = INode.NODE_ID_SMB_SHARE;
                    N.NodeData = new INodeData_SMB_SHARE();

                    if (FExpand_Level == 1)
                    {
                        IWin32.SHARE_INFO_1 si = (IWin32.SHARE_INFO_1)System.Runtime.InteropServices.Marshal.PtrToStructure(new IntPtr(lpItem), t);
                        ((INodeData_SMB_SHARE)N.NodeData).ShareNetName = si.NetName;
                        ((INodeData_SMB_SHARE)N.NodeData).SharePath = "";
                        ((INodeData_SMB_SHARE)N.NodeData).ShareType = si.ShareType;
                        ((INodeData_SMB_SHARE)N.NodeData).ShareRemark = si.Remark;
                    }
                    else
                    {
                        IWin32.SHARE_INFO_2 si = (IWin32.SHARE_INFO_2)System.Runtime.InteropServices.Marshal.PtrToStructure(new IntPtr(lpItem), t);
                        ((INodeData_SMB_SHARE)N.NodeData).ShareNetName = si.NetName;
                        ((INodeData_SMB_SHARE)N.NodeData).SharePath = si.Path;
                        ((INodeData_SMB_SHARE)N.NodeData).ShareType = si.ShareType;
                        ((INodeData_SMB_SHARE)N.NodeData).ShareRemark = si.Remark;
                    }

                    if (!ExpandMode_AddAdminShare) // Maju sa vyhodit admin zdielania?
                    {
                        switch (((INodeData_SMB_SHARE)N.NodeData).ShareType)
                        {
                            case IWin32.ShareType.Disk:
                            case IWin32.ShareType.Printer:
                                break;
                            default:
                                {
                                    if (Result == null) N.Dispose();
                                    N = null;
                                } break;
                        }
                    }

                    FExpand_CurrentIndex++; // Dalsi zaznam
                    if (N != null)
                    {
                        if (Result == null) AddNode(N);
                        return 1;
                    }
                }
            }
            catch
            {
                return -1;
            }
        }

        /// <summary>Vytvorenie textov pre zobrazenie</summary>
        /// <param name="pNode">objekt node</param>
        public override void CreateDisplayStrings(INode pNode)
        {
            if (pNode.DisplayStrings != null) return; // Uz su vytvorenie?

            pNode.DisplayStrings = new string[ColsCount]; // Alokujem retazec
            switch (pNode.ID) // Podla typu node
            {
                case INode.NODE_ID_BACK_ITEM:
                    {
                        pNode.DisplayStrings[0] = ICore.BoundString("[", "..", "]", IApp.Settings.FileExplorer_DirsInBraces);
                        pNode.DisplayStrings[1] = lang.NODE_LIST_SMB_SHARES_TEXT_5;
                        pNode.DefaultImageIndex = -1;
                    } break;
                case INode.NODE_ID_SMB_SHARE:
                    {
                        pNode.DisplayStrings[0] = ICore.BoundString("[", ((INodeData_SMB_SHARE)pNode.NodeData).ShareNetName, "]", IApp.Settings.FileExplorer_DirsInBraces);
                        pNode.DisplayStrings[2] = ((INodeData_SMB_SHARE)pNode.NodeData).SharePath;
                        pNode.DisplayStrings[3] = ((INodeData_SMB_SHARE)pNode.NodeData).ShareRemark;
                        switch (((INodeData_SMB_SHARE)pNode.NodeData).ShareType)
                        {
                            case IWin32.ShareType.Device: pNode.DisplayStrings[1] = lang.NODE_LIST_SMB_SHARES_TEXT_6_1; break;
                            case IWin32.ShareType.Disk: pNode.DisplayStrings[1] = lang.NODE_LIST_SMB_SHARES_TEXT_6_2; break;
                            case IWin32.ShareType.IPC: pNode.DisplayStrings[1] = lang.NODE_LIST_SMB_SHARES_TEXT_6_3; break;
                            case IWin32.ShareType.Printer: pNode.DisplayStrings[1] = lang.NODE_LIST_SMB_SHARES_TEXT_6_4; break;
                            default: pNode.DisplayStrings[1] = lang.NODE_LIST_SMB_SHARES_TEXT_6_5; break;
                        }
                        pNode.DefaultImageIndex = 0;
                    } break;
            }
        }
        /// <summary>Vytvorenie klonu zoznamu</summary>
        /// <returns>objekt zoznamu</returns>
        public override INodeList CloneList()
        {
            return new INodeList_SMB_SHARES(CurrentPath);
        }
    }
}
